﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Onshi.POS.AccesoDatos;
using Onshi.POS.AccesoDatos.Interfaces;
using Onshi.POS.Modelo.Entidades;
using Onshi.POS.Modelo.Objetos;

namespace Onshi.POS.Repositorios
{
    public class RepositorioProveedor : RepositorioEntidad<Proveedor, Int32>
    {
        #region Constructores

        public RepositorioProveedor()
            : base()
        {
            servicioDatosProveedor = new ServicioDatosProveedor();
            repositorioRubroProveedor = new RepositorioRubroProveedor();
            repositorioTipoIva = new RepositorioTipoIva();
            repositorioTipoDomicilio = new RepositorioTipoDomicilio();
            repositorioBarrio = new RepositorioBarrio();
            repositorioTipoTelefono = new RepositorioTipoTelefono();
            repositorioTipoMensajeriaInstantanea = new RepositorioTipoMensajeriaInstantanea();
        }
        #endregion

        #region Atributos
        private IServicioDatosProveedor servicioDatosProveedor;
        private RepositorioRubroProveedor repositorioRubroProveedor;
        private RepositorioTipoIva repositorioTipoIva;

        private RepositorioTipoDomicilio repositorioTipoDomicilio;
        private RepositorioTipoTelefono repositorioTipoTelefono;
        private RepositorioTipoMensajeriaInstantanea repositorioTipoMensajeriaInstantanea;
        private RepositorioBarrio repositorioBarrio;
        #endregion

        #region Propiedades

        public RepositorioTipoIva RepositorioTipoIva
        {
            get { return repositorioTipoIva; }
            set { repositorioTipoIva = value; }
        }

        private RepositorioBarrio RepositorioBarrio
        {
            get { return repositorioBarrio; }
        }

        private RepositorioTipoTelefono RepositorioTipoTelefono
        {
            get { return repositorioTipoTelefono; }
        }

        private RepositorioTipoDomicilio RepositorioTipoDomicilio
        {
            get { return repositorioTipoDomicilio; }
        }

        public RepositorioRubroProveedor RepositorioRubroProveedor
        {
            get { return repositorioRubroProveedor; }
            set { repositorioRubroProveedor = value; }
        }

        private IServicioDatosProveedor ServicioDatosProveedor
        {
            get { return servicioDatosProveedor; }
        }

        #endregion

        #region Metodos

        public List<Proveedor> DevolverTodos()
        {
            using (DataSet ds = ServicioDatosProveedor.Proveedor_DevolverTodos())
            {
                entidades = TablaALista(ds.Tables[0]);
            }
            return entidades;
        }

        public void Insertar(Proveedor proveedor)
        {
            proveedor.Id = servicioDatosProveedor.Proveedor_Insertar(proveedor.Rubro.Id, proveedor.TipoIva.Id, proveedor.ListaPrecioCompra.Id, proveedor.Codigo, proveedor.Nombre, proveedor.Email, proveedor.SitioWeb, proveedor.EstaEliminado, proveedor.Cuit);
        }

        public void Modificar(Proveedor proveedor)
        {
            ServicioDatosProveedor.Proveedor_Modificar(proveedor.Id, proveedor.Rubro.Id, proveedor.TipoIva.Id, proveedor.ListaPrecioCompra.Id, proveedor.Codigo, proveedor.Nombre, proveedor.Email, proveedor.SitioWeb, proveedor.EstaEliminado, proveedor.Cuit);
        }

        public void Eliminar(Proveedor proveedor)
        {
            servicioDatosProveedor.Proveedor_Eliminar(proveedor.Id);
            proveedor = null;
        }

        public override Proveedor DevolverPorId(Int32 id)
        {
            Proveedor entidad = (from Proveedor item in entidades where item.Id == id select item).FirstOrDefault();
            if (entidad == null)
            {
                using (DataSet ds = servicioDatosProveedor.Proveedor_DevolverPorId(id))
                {
                    if (ds.Tables[0].Rows.Count != 0)
                    {
                        entidad = FilaAEntidad(ds.Tables[0].Rows[0]);
                        entidades.Add(entidad);
                    }
                }
            }
            return entidad;
        }

        protected override Proveedor FilaAEntidad(DataRow fila)
        {
            Proveedor proveedor = new Proveedor();
            proveedor.Codigo = (String)fila["Codigo"];
            proveedor.Cuit = fila["Cuit"].ToString();
            proveedor.Email = (String)fila["Email"];
            proveedor.EstaEliminado = (Boolean)fila["EstaEliminado"];
            proveedor.SitioWeb = (String)fila["SitioWeb"];
            proveedor.Rubro = RepositorioRubroProveedor.DevolverPorId((Int32)fila["IdRubroProveedor"]);
            proveedor.TipoIva = RepositorioTipoIva.DevolverPorId((Byte)fila["IdTipoIva"]);
            proveedor.Rubro = RepositorioRubroProveedor.DevolverPorId((Int32)fila["IdRubroProveedor"]);

            if (fila.Table.Columns.Contains("TieneDomicilios"))
                proveedor.TieneDomicilios = (Boolean)fila["TieneDomicilios"];
            if (fila.Table.Columns.Contains("TieneImagen"))
                proveedor.TieneImagen = (Boolean)fila["TieneImagen"];
            if (fila.Table.Columns.Contains("TieneObservacion"))
               proveedor.TieneObservacion = (Boolean)fila["TieneObservacion"];
            if (fila.Table.Columns.Contains("TieneTelefonos"))
                proveedor.TieneTelefonos = (Boolean)fila["TieneTelefonos"];
            return proveedor;
        }

        public Proveedor DevolverPorIdConDetalleDomiciliosTelefonos(Int32 id)
        {
            var entidad = (from Proveedor item in entidades
                           where item.Id == id
                           && item.Detalle != null
                           && item.Domicilios != null
                           && item.Telefonos != null
                           select item).FirstOrDefault();
            if (entidad == null)
            {
                using (DataSet ds = ServicioDatosProveedor.Proveedores_DevolverPorIdConDetalleDomiciliosTelefonos(id))
                {
                    if (ds.Tables[0].Rows.Count != 0)
                    {
                        entidad = FilaAEntidad(ds.Tables[0].Rows[0]);
                        entidad.Detalle = FilaADetalle(ds.Tables[1].Rows[0], entidad);
                        entidad.Domicilios = TablaAListaDomicilios(ds.Tables[2], entidad);
                        entidad.Telefonos = TablaAListaTelefonos(ds.Tables[3], entidad);
                        entidades.Add(entidad);
                    }
                }
            }
            return entidad;
        }

        private DetalleProveedor FilaADetalle(DataRow fila, Proveedor proveedor)
        {
            var detalle = new DetalleProveedor();
            detalle.Proveedor = proveedor;
            detalle.Observacion = (String)fila["Observacion"];
            if (fila["Imagen"] != DBNull.Value)
                detalle.Imagen = ManejoImagen.ByteAImagen((Byte[])fila["Imagen"]);
            return detalle;
        }

        private DomicilioProveedor FilaADomicilio(DataRow fila, Proveedor proveedor)
        {
            var domicilio = new DomicilioProveedor();
            domicilio.Proveedor = proveedor;
            domicilio.Id = (Int32)fila["IdDomicilioProveedor"];
            domicilio.Tipo = RepositorioTipoDomicilio.DevolverPorId((Byte)fila["IdTipoDomicilio"]);
            domicilio.Barrio = RepositorioBarrio.DevolverPorId((Int32)fila["IdBarrio"]);
            domicilio.Calle = (String)fila["Calle"];
            domicilio.Numero = (String)fila["Numero"];
            domicilio.Piso = (String)fila["Piso"];
            domicilio.Departamento = (String)fila["Departamento"];
            domicilio.Observacion = (String)fila["Observacion"];
            return domicilio;
        }

        private TelefonoProveedor FilaATelefono(DataRow fila, Proveedor proveedor)
        {
            var telefono = new TelefonoProveedor();
            telefono.Proveedor = proveedor;
            telefono.Id = (Int32)fila["IdTelefonoVendedor"];
            telefono.Tipo = RepositorioTipoTelefono.DevolverPorId((Byte)fila["IdTipoTelefono"]);
            telefono.CodigoArea = (String)fila["CodigoArea"];
            telefono.Numero = (String)fila["Numero"];
            telefono.Observacion = (String)fila["Observacion"];
            return telefono;
        }

        private List<TelefonoProveedor> TablaAListaTelefonos(DataTable tabla, Proveedor proveedor)
        {
            var lista = new List<TelefonoProveedor>();
            foreach (DataRow fila in tabla.Rows)
            {
                lista.Add(FilaATelefono(fila, proveedor));
            }
            return lista;
        }

        private List<DomicilioProveedor> TablaAListaDomicilios(DataTable tabla, Proveedor proveedor)
        {
            var lista = new List<DomicilioProveedor>();
            foreach (DataRow fila in tabla.Rows)
            {
                lista.Add(FilaADomicilio(fila, proveedor));
            }
            return lista;
        }

        public void EliminarTelefonosPorProveedor(Proveedor proveedor)
        {
            ServicioDatosProveedor.TelefonosProveedores_EliminarPorProveedor(proveedor.Id); 
        }

        public void InsertarDetalle(DetalleProveedor detalle)
        {
            ServicioDatosProveedor.ProveedorDetalles_Insertar(detalle.Proveedor.Id, detalle.Observacion, ManejoImagen.ImagenAByte(detalle.Imagen));
        }

        public void ModificarDetalle(DetalleProveedor detalle)
        {
            servicioDatosProveedor.ProveedorDetalles_Modificar(detalle.Proveedor.Id, detalle.Observacion, ManejoImagen.ImagenAByte(detalle.Imagen));
        }

        public void EliminarDomiciliosPorProveedor(Proveedor proveedor)
        {
            ServicioDatosProveedor.DomiciliosProveedores_EliminarPorProveedor(proveedor.Id);
        }
        
        public void InsertarDomicilio(DomicilioProveedor domicilio)
        {
            domicilio.Id = servicioDatosProveedor.DomiciliosProveedores_Insertar(domicilio.Proveedor.Id, domicilio.Tipo.Id, domicilio.Barrio.Id, domicilio.Calle, domicilio.Numero, domicilio.Piso, domicilio.Departamento, domicilio.Observacion);
        }

        public void InsertarTelefono(TelefonoProveedor telefono)
        {
            telefono.Id = ServicioDatosProveedor.TelefonosProveedores_Insertar(telefono.Proveedor.Id, telefono.Tipo.Id, telefono.CodigoArea, telefono.Numero, telefono.Observacion);
        }
        #endregion
    }
}
